package dataTypeTests;

import java.util.Collection;
import java.util.Iterator;

public class OneWayList<T>{
	private T data;
	private OneWayList<T> next;
	
	OneWayList(T data) {
		this.data = data;
		next = null;
	}
	
	OneWayList(T[] data) {
		this.data = data[0];
		next = null;
		OneWayList<T> last = this;
		for (int i = 1; i < data.length; i++) {
			last.add(data[i]);
			last = last.getNext();
		}
	}
	
	OneWayList(Collection<T> data) {
		next = null;
		OneWayList<T> last = this;
		Iterator<T> dataIterator = data.iterator();
		this.data = dataIterator.next();
		while(dataIterator.hasNext()) {
			last.add(dataIterator.next());
			last = last.getNext();
		}
	}
	
	OneWayList() {
		data = null;
		next = null;
	}
	
	public T getData() {return data;}
	public T getData(int index) {
		OneWayList<T> nextElem = this;
		int i = index;
		while ((nextElem.getNext() != null)&&(i > 0)) {
			nextElem = nextElem.getNext();
			--i;
		}
		if (i > 0) throw new IndexOutOfBoundsException("Index: "+index+", Size: "+(index-i+1));
		return nextElem.getData();
	}
	
	public void setData(T data) {this.data = data;}
	
	public OneWayList<T> getNext() {return next;}
	public OneWayList<T> getElem(int index) {
		OneWayList<T> nextElem = this;
		int i = index;
		while ((nextElem.getNext() != null)&&(i > 0)) {
			nextElem = nextElem.getNext();
			--i;
		}
		if (i > 0) throw new IndexOutOfBoundsException("Index: "+index+", Size: "+(index-i+1));
		return nextElem;
	}
	
	public void insert(OneWayList<T> list) {
		if (next == null) next = list;
		else {
			OneWayList<T> nextElem = this.next;
			this.next = list;
			while (list.getNext() != null) {
				list = list.getNext();
			}
			list.insert(nextElem);
		}
	}
	
	public void insert(T data) {
		OneWayList<T> nextElem = this.next;
		this.next = new OneWayList<T>(data);
		this.next.insert(nextElem);
	}
	
	public void insert(int pos, T data) {
		OneWayList<T> nextElem = this;
		int size = 1;
		if (pos < 0) throw new IndexOutOfBoundsException("Index: "+pos);
		while ((nextElem.getNext() != null) && (pos > 1)) {
			nextElem = nextElem.getNext();
			--pos;
			++size;
		}
		if (pos > 1) throw new IndexOutOfBoundsException("Index: "+(pos+size-1)+", Size: "+size);
		nextElem.insert(data);
	}
	
	public void add(T data) {
		OneWayList<T> nextElem = this.next;
		if (nextElem == null) {
			this.insert(data);
			return;
		}
		while (nextElem.getNext() != null) {
			nextElem = nextElem.getNext();
		}
		nextElem.insert(data);
	}
	
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append('[' + this.data.toString());
		OneWayList<T> list = this.next;
		while (list != null) {
			buffer.append(", " + list.data.toString());
			list = list.getNext();
		}
		buffer.append(']');
		return buffer.toString();
	}
}
